//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "spi_bsp.h"
#include "gd32f4xx.h"
#include "gd32f4xx_spi.h"
#include "gd32f4xx_misc.h"
#include "gd32f4xx_rcu.h"
#include <string.h>
#include <stdlib.h>

#ifndef NULL
#define NULL ((void*)0)
#endif

typedef struct
{
    void (*GPIO_Init_CB)(void);
}WHT_SPI_GPIO_t;

/*SPI总线结构体*/
typedef struct
{
    WHT_SPI_BUS_t Info;       //总线信息
    unsigned int Delay_Count; //延迟时间
    unsigned int SPI_BUS;     //总线外设
    WHT_SPI_GPIO_t GPIO;      //总线GPIO
    WHT_SPI_Cache_t* Cache;   //外设缓存,由外部设备提供
	ControlStatus DMA_State;//DMA状态
    WHT_DMA_Config_t DMA_Send_Config;   //DMA发送配置
    WHT_DMA_Config_t DMA_Receive_Config;//DMA接收配置
}WHT_SPI_BUS_Private_t;


static WHT_SPI_BUS_Private_t* WHT_SPI_BUS[6];//SPI总线6个

#define WHT_BUS        ((WHT_SPI_BUS_Private_t*)bus)


/*SPI回调用户的中断函数*/
static void WHT_SPI_BSP_User_IT_Callback(WHT_SPI_BUS_Private_t* BUS)
{
    *(WHT_SPI_BUS_Lock_enum*)&BUS->Info.Mutex = SPI_Unlock;
    if (BUS->Cache->TRx_Finish_IT_CB != NULL)
        BUS->Cache->TRx_Finish_IT_CB();
}

/*SPI DMA发送回调函数*/
static void WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS_Private_t* BUS)
{
	spi_dma_disable(BUS->SPI_BUS, SPI_DMA_TRANSMIT);//Close Tx DMA
	if (BUS->DMA_Send_Config.Info->State == TRx_TC)//发送完成
	{
		if (BUS->Cache->Dir == SPI_WO)
		{
			while(spi_i2s_flag_get(BUS->SPI_BUS, SPI_FLAG_TRANS) == SET);//死等待发送完成
			spi_i2s_data_receive(BUS->SPI_BUS);                          //丢掉接收的数据,clear rx_it_over
			if (BUS->Info.Config.NSS == Soft_NSS)
				BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
			spi_disable(BUS->SPI_BUS);//Close SPI
			BUS->DMA_State = DISABLE;      //close dma flag
			WHT_SPI_BSP_User_IT_Callback(BUS);
		}
	}
	else if (BUS->DMA_Send_Config.Info->State == TRx_TE)//发送失败
	{
		spi_dma_disable(BUS->SPI_BUS, SPI_DMA_RECEIVE);//Close Rx DMA
		if (BUS->Cache->Dir != SPI_WO)
			WHT_DMA_BSP.WHT_Close(&BUS->DMA_Receive_Config);
		spi_i2s_data_receive(BUS->SPI_BUS);                       //丢掉接收的数据,clear rx_it_over
		if (BUS->Info.Config.NSS == Soft_NSS)
			BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
		spi_disable(BUS->SPI_BUS);//Close SPI
		BUS->DMA_State = DISABLE;      //close dma flag
		*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_BUS_Error;//error
		WHT_SPI_BSP_User_IT_Callback(BUS);
	}
}
/*SPI DMA接收回调函数*/
static void WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS_Private_t* BUS)
{
	spi_dma_disable(BUS->SPI_BUS, SPI_DMA_TRANSMIT);//Close Tx/Rx DMA
	spi_dma_disable(BUS->SPI_BUS, SPI_DMA_RECEIVE);
	if (BUS->DMA_Receive_Config.Info->State == TRx_TE)
	{	
		WHT_DMA_BSP.WHT_Close(&BUS->DMA_Receive_Config);
		*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_BUS_Error;//error
	}
	if (BUS->Info.Config.NSS == Soft_NSS)
		BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
	spi_disable(BUS->SPI_BUS);//Close SPI
	BUS->DMA_State = DISABLE;      //close dma flag
	WHT_SPI_BSP_User_IT_Callback(BUS);
}
/*SPI DMA发送接收回调函数*/
static void WHT_SPI_BSP_DMA_Send_Receive_Callback(WHT_SPI_BUS_Private_t* BUS)
{
	spi_dma_disable(BUS->SPI_BUS, SPI_DMA_TRANSMIT);//Close Tx/Rx DMA
	spi_dma_disable(BUS->SPI_BUS, SPI_DMA_RECEIVE);
	WHT_DMA_BSP.WHT_Close(&BUS->DMA_Send_Config);
	if (BUS->Cache->Dir != SPI_WO)
		WHT_DMA_BSP.WHT_Close(&BUS->DMA_Receive_Config);
	spi_i2s_data_receive(BUS->SPI_BUS);                     //丢掉接收的数据,clear rx_it_over
	spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_ERR);//Close Err Interrupt
	if (BUS->Info.Config.NSS == Soft_NSS)
		BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
	spi_disable(BUS->SPI_BUS);//Close SPI
	BUS->DMA_State = DISABLE;
	*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_Rx_Over_Error;//error
	WHT_SPI_BSP_User_IT_Callback(BUS);
}

/*SPI1 DMA发送回调函数*/
static void WHT_SPI1_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[0]);
}
/*SPI1 DMA接收回调函数*/
static void WHT_SPI1_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[0]);
}
/*SPI2 DMA发送回调函数*/
static void WHT_SPI2_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[1]);
}
/*SPI2 DMA接收回调函数*/
static void WHT_SPI2_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[1]);
}
/*SPI3 DMA发送回调函数*/
static void WHT_SPI3_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[2]);
}
/*SPI3 DMA接收回调函数*/
static void WHT_SPI3_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[2]);
}
/*SPI4 DMA发送回调函数*/
static void WHT_SPI4_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[3]);
}
/*SPI4 DMA接收回调函数*/
static void WHT_SPI4_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[3]);
}
/*SPI5 DMA发送回调函数*/
static void WHT_SPI5_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[4]);
}
/*SPI5 DMA接收回调函数*/
static void WHT_SPI5_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[4]);
}
/*SPI6 DMA发送回调函数*/
static void WHT_SPI6_BSP_DMA_Send_Callback(void)
{
	WHT_SPI_BSP_DMA_Send_Callback(WHT_SPI_BUS[5]);
}
/*SPI6 DMA接收回调函数*/
static void WHT_SPI6_BSP_DMA_Receive_Callback(void)
{
	WHT_SPI_BSP_DMA_Receive_Callback(WHT_SPI_BUS[5]);
}


/*SPI 发送和接收*/
static void WHT_SPI_BUS_Read_Write(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache)
{
	unsigned int wait_bus_idle;
	
	*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Lock;
	*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_No_Error;
	WHT_BUS->Cache = cache;

	spi_enable(WHT_BUS->SPI_BUS);
	if (WHT_BUS->Info.Config.NSS == Soft_NSS)
		WHT_BUS->Cache->Set_NSS_State_CB(SPI_IO_Low);
	else
	{
		wait_bus_idle = WHT_BUS->Delay_Count;
		if ((spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_TRANS) != RESET) || (spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_CONFERR) != RESET))//其它主设备在通信
		{
			if (wait_bus_idle-- == 0)
			{
				spi_disable(WHT_BUS->SPI_BUS);//close SPI
				*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_BUS_Error;
				*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
				return;
			}
			spi_enable(WHT_BUS->SPI_BUS);
		}
	}
	for (unsigned int i = 0; i < WHT_BUS->Cache->Buffer_Count; i++)
	{
		spi_i2s_data_transmit(WHT_BUS->SPI_BUS, WHT_BUS->Cache->Tx_Buffer[i]);
		if (WHT_BUS->Cache->Dir == SPI_WO)
		{
			while (spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_TBE) == RESET);//TXE事件
		}
		else//SPI_TRx SPI_RO
		{
			while (spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_RBNE) == RESET);//RXE事件
			WHT_BUS->Cache->Rx_Buffer[i] =(unsigned char)spi_i2s_data_receive(WHT_BUS->SPI_BUS);
		}
	}
	while (spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_TRANS) == SET);
	spi_i2s_data_receive(WHT_BUS->SPI_BUS);//Clear Over
	if (WHT_BUS->Info.Config.NSS == Soft_NSS)
		WHT_BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
	spi_disable(WHT_BUS->SPI_BUS);
	*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
}
/*SPI 中断发送和接收*/
static void WHT_SPI_BUS_Read_Write_IT(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache)
{
	unsigned int wait_bus_idle;

	*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Lock;
	*(WHT_SPI_BUS_State_enum *)&WHT_BUS->Info.State = SPI_No_Error;
	WHT_BUS->Cache = cache;

	spi_enable(WHT_BUS->SPI_BUS);
	if (WHT_BUS->Info.Config.NSS == Soft_NSS)
		WHT_BUS->Cache->Set_NSS_State_CB(SPI_IO_Low);
	else
	{
		wait_bus_idle = WHT_BUS->Delay_Count;
		if ((spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_TRANS) != RESET) || (spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_CONFERR) != RESET))//其它主设备在通信
		{
			if (wait_bus_idle-- == 0)
			{
				spi_disable(WHT_BUS->SPI_BUS);//close SPI
				*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_BUS_Error;
				*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
				return;
			}
			spi_enable(WHT_BUS->SPI_BUS);
		}
	}
	spi_i2s_interrupt_enable(WHT_BUS->SPI_BUS, SPI_I2S_INT_ERR);
	spi_i2s_interrupt_enable(WHT_BUS->SPI_BUS, SPI_I2S_INT_RBNE);
	spi_i2s_interrupt_enable(WHT_BUS->SPI_BUS, SPI_I2S_INT_TBE);//使能则发送连续但有风险
}
/*SPI DMA发送和接收*/
static void WHT_SPI_BUS_Read_Write_DMA(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache)
{
    unsigned int wait_bus_idle;

    dma_single_data_parameter_struct DMA_Send_InitStruct =
    {
        //.periph_addr            = (unsigned int)0,            //外设地址
        //.memory0_addr           = (unsigned int)0,            //存储器地址
        .direction              = DMA_MEMORY_TO_PERIPH,       //M->P
        //.number                 = 0,                          //传输个数
        .circular_mode          = DMA_CIRCULAR_MODE_DISABLE,  //单次模式
        .periph_inc             = DMA_PERIPH_INCREASE_DISABLE,//外设地址不递增
        .memory_inc             = DMA_MEMORY_INCREASE_ENABLE, //存储器地址递增
        .periph_memory_width    = DMA_PERIPH_WIDTH_8BIT,      //外设数据大小为字节
        .priority               = DMA_PRIORITY_LOW,           //优先级最低
    };

    dma_single_data_parameter_struct DMA_Receive_InitStruct =
    {
        //.periph_addr            = (unsigned int)0,            //外设地址
        //.memory0_addr           = (unsigned int)0,            //存储器地址
        .direction              = DMA_PERIPH_TO_MEMORY,       //P->M
        //.number                 = 0,                          //传输个数
        .circular_mode          = DMA_CIRCULAR_MODE_DISABLE,  //单次模式
        .periph_inc             = DMA_PERIPH_INCREASE_DISABLE,//外设地址不递增
        .memory_inc             = DMA_MEMORY_INCREASE_ENABLE, //存储器地址递增
        .periph_memory_width    = DMA_PERIPH_WIDTH_8BIT,      //外设数据大小为字节
        .priority               = DMA_PRIORITY_LOW,           //优先级最低
    };

	*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Lock;
	*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_No_Error;
	WHT_BUS->Cache = cache;
	if (WHT_BUS->Info.Config.Bit_Wide == SPI_16Bit_Wide)
	{
		DMA_Send_InitStruct.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;//外设数据大小为字节
		DMA_Receive_InitStruct.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;//外设数据大小为字节
	}

	DMA_Send_InitStruct.periph_addr = WHT_BUS->SPI_BUS + 0x0CU;                //外设基地址 
	DMA_Send_InitStruct.memory0_addr = (unsigned int)WHT_BUS->Cache->Tx_Buffer;//数据源首地址
	DMA_Send_InitStruct.number = WHT_BUS->Cache->Buffer_Count;                 //传输数据个数
	WHT_BUS->DMA_Send_Config.DMA_InitStruct = &DMA_Send_InitStruct;
	while (WHT_BUS->DMA_Send_Config.Info->BSP_Mutex == SET);//等待没有外设使用此通道的DMA
	WHT_BUS->DMA_Send_Config.Info->BSP_Mutex = SET;         //DMA通道上锁
	WHT_DMA_BSP.WHT_Config(&WHT_BUS->DMA_Send_Config);      //配置当前DMA

	if (WHT_BUS->Cache->Dir != SPI_WO)
	{
		DMA_Receive_InitStruct.periph_addr = WHT_BUS->SPI_BUS + 0x0CU;                //外设基地址
		DMA_Receive_InitStruct.memory0_addr = (unsigned int)WHT_BUS->Cache->Rx_Buffer;//数据源首地址
		DMA_Receive_InitStruct.number = WHT_BUS->Cache->Buffer_Count;                 //传输数据个数
		WHT_BUS->DMA_Receive_Config.DMA_InitStruct = &DMA_Receive_InitStruct;
		while (WHT_BUS->DMA_Receive_Config.Info->BSP_Mutex == SET);//等待没有外设使用此通道的DMA
		WHT_BUS->DMA_Receive_Config.Info->BSP_Mutex = SET;         //DMA通道上锁
		WHT_DMA_BSP.WHT_Config(&WHT_BUS->DMA_Receive_Config);      //配置当前DMA
	}

    //检测总线状态
	wait_bus_idle = WHT_BUS->Delay_Count;
	spi_enable(WHT_BUS->SPI_BUS);//Open SPI
	if (WHT_BUS->Info.Config.NSS == Soft_NSS)
		WHT_BUS->Cache->Set_NSS_State_CB(SPI_IO_Low);
	else
	{
		if ((spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_TRANS) != RESET) || (spi_i2s_flag_get(WHT_BUS->SPI_BUS, SPI_FLAG_CONFERR) != RESET))//其它主设备在通信
		{
			if (wait_bus_idle-- == 0)
			{
				if (WHT_BUS->Cache->Dir != SPI_WO)
					WHT_DMA_BSP.WHT_Close(&WHT_BUS->DMA_Receive_Config);//close dma
				WHT_DMA_BSP.WHT_Close(&WHT_BUS->DMA_Send_Config);       //close dma
				spi_disable(WHT_BUS->SPI_BUS);                          //close SPI
				*(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_BUS_Error;
				*(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
				return;
			}
			spi_enable(WHT_BUS->SPI_BUS);
		}
	}

	WHT_BUS->DMA_State = ENABLE;		
	if (WHT_BUS->Cache->Dir != SPI_WO)
	{
		spi_i2s_interrupt_disable(WHT_BUS->SPI_BUS, SPI_I2S_INT_ERR);//close IT Error 一定不能开启
		spi_dma_enable(WHT_BUS->SPI_BUS, SPI_DMA_RECEIVE);//使能DMA请求
	}
	spi_dma_enable(WHT_BUS->SPI_BUS, SPI_DMA_TRANSMIT);//使能DMA请求
}


/*SPI总线配置*/
static void WHT_SPI_BUS_Config(WHT_SPI_BUS_t* bus)
{
	spi_parameter_struct SPI_InitStruct;
	
	/*临时关闭串口*/
	spi_disable(WHT_BUS->SPI_BUS);
	/*SPI相关GPIO初始化*/
    WHT_BUS->GPIO.GPIO_Init_CB();

	switch (WHT_BUS->Info.Config.Work_Mode)
	{
	case SPI_Work_Mode0:SPI_InitStruct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; break;
	case SPI_Work_Mode1:SPI_InitStruct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE; break;
	case SPI_Work_Mode2:SPI_InitStruct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE;break;
	case SPI_Work_Mode3:SPI_InitStruct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;break;
	}

    /*初始化配置SPI相关寄存器*/
	SPI_InitStruct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
	SPI_InitStruct.frame_size           = WHT_BUS->Info.Config.Bit_Wide == SPI_8Bit_Wide ? SPI_FRAMESIZE_8BIT : SPI_FRAMESIZE_16BIT;
	SPI_InitStruct.endian               = WHT_BUS->Info.Config.MSB_LSB == 0 ? SPI_ENDIAN_MSB : SPI_ENDIAN_LSB;
	SPI_InitStruct.device_mode          = WHT_BUS->Info.Config.Master_Slave == 0 ? SPI_MASTER : SPI_SLAVE;
	SPI_InitStruct.nss                  = WHT_BUS->Info.Config.NSS == Soft_NSS ? SPI_NSS_SOFT : SPI_NSS_HARD;;
	SPI_InitStruct.prescale             = WHT_BUS->Info.Config.Clock_Div;////SPI_PSC_2;

	spi_init(WHT_BUS->SPI_BUS, &SPI_InitStruct);
	spi_crc_polynomial_set(WHT_BUS->SPI_BUS, 7);//校验默认值
	spi_crc_off(WHT_BUS->SPI_BUS);              //close spi crc

	WHT_BUS->Delay_Count = ((((WHT_BUS->Info.Config.Clock_Div >> 3) + 1) << 1) << 0) * (WHT_BUS->Info.Config.Bit_Wide == SPI_8Bit_Wide ? 8 : 16);//延迟时间

	spi_i2s_interrupt_disable(WHT_BUS->SPI_BUS, SPI_I2S_INT_TBE);
	spi_i2s_interrupt_disable(WHT_BUS->SPI_BUS, SPI_I2S_INT_RBNE);
	spi_i2s_interrupt_disable(WHT_BUS->SPI_BUS, SPI_I2S_INT_ERR);

	if (WHT_BUS->Info.Config.NSS == Hard_NSS)/*如果硬件管控NSS，想要释放NSS则需要关闭SPI功能，且必须引脚有上拉电阻*/
		spi_nss_output_enable(WHT_BUS->SPI_BUS);
	else
		spi_nss_output_disable(WHT_BUS->SPI_BUS);
}
/*SPI中断优先级配置*/
static void WHT_SPI_BUS_NVIC_Configuration(WHT_SPI_BUS_t* bus)
{
	/* 配置中断源 */
    if (strcmp(WHT_BUS->Info.Name, WHT_SPI1_Name) == 0)
	{
		NVIC_SetPriority(SPI0_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI0_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI2_Name) == 0)
	{
		NVIC_SetPriority(SPI1_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI1_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI3_Name) == 0)
	{
		NVIC_SetPriority(SPI2_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI2_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI4_Name) == 0)
	{
		NVIC_SetPriority(SPI3_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI3_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI5_Name) == 0)
	{
		NVIC_SetPriority(SPI4_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI4_IRQn);
	}
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI6_Name) == 0)
	{
		NVIC_SetPriority(SPI5_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(SPI5_IRQn);
	}
}
/*总线初始化*/
static void WHT_SPI_BUS_Init(WHT_SPI_BUS_t* bus)
{
    if (strcmp(WHT_BUS->Info.Name, WHT_SPI1_Name) == 0)
    {
		rcu_periph_clock_enable(RCU_SPI0);
		WHT_BUS->SPI_BUS = SPI0;
    }
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI2_Name) == 0)
    {
		rcu_periph_clock_enable(RCU_SPI1);
        WHT_BUS->SPI_BUS = SPI1;
    }
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI3_Name) == 0)
	{
		rcu_periph_clock_enable(RCU_SPI2);
		WHT_BUS->SPI_BUS = SPI2;
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI4_Name) == 0)
	{
		rcu_periph_clock_enable(RCU_SPI3);
		WHT_BUS->SPI_BUS = SPI3;
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI5_Name) == 0)
	{
		rcu_periph_clock_enable(RCU_SPI4);
		WHT_BUS->SPI_BUS = SPI4;
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI6_Name) == 0)
	{
		rcu_periph_clock_enable(RCU_SPI5);
		WHT_BUS->SPI_BUS = SPI5;
	}
    else
        return;

    *(WHT_SPI_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = SPI_Unlock;
    *(WHT_SPI_BUS_State_enum*)&WHT_BUS->Info.State = SPI_No_Error;    
    WHT_BUS->Cache = NULL;
    WHT_BUS->DMA_Send_Config.IT_Callback = NULL;
    WHT_BUS->DMA_Receive_Config.IT_Callback = NULL;
    WHT_BUS->DMA_State = DISABLE;

	/*注册DMA*/
    if (strcmp(WHT_BUS->Info.Name, WHT_SPI1_Name) == 0)
    {
		WHT_BUS->DMA_Send_Config.Periph = Periph_SPI1_TX_1;
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI1_TX_1;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI1_TX_1;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI1_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Periph = Periph_SPI1_RX_1;
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI1_RX_1;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI1_RX_1;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI1_BSP_DMA_Receive_Callback;//DMA Callback
    }
    else if (strcmp(WHT_BUS->Info.Name, WHT_SPI2_Name) == 0)
    {
		WHT_BUS->DMA_Send_Config.Periph = Periph_SPI2_TX;
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI2_TX;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI2_TX;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI2_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Periph = Periph_SPI2_RX;
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI2_RX;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI2_RX;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI2_BSP_DMA_Receive_Callback;//DMA Callback
    }
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI3_Name) == 0)
	{
		WHT_BUS->DMA_Send_Config.Periph = Periph_SPI3_TX_1;
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI3_TX_1;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI3_TX_1;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI3_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Periph = Periph_SPI3_RX_1;
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI3_RX_1;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI3_RX_1;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI3_BSP_DMA_Receive_Callback;//DMA Callback
	}

	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI4_Name) == 0)
	{
		WHT_BUS->DMA_Send_Config.Periph = Periph_SPI4_TX_1;
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI4_TX_1;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI4_TX_1;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI4_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Periph = Periph_SPI4_RX_1;
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI4_RX_1;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI4_RX_1;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI4_BSP_DMA_Receive_Callback;//DMA Callback
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI5_Name) == 0)
	{
		WHT_BUS->DMA_Send_Config.Periph = Periph_SPI5_TX_1;
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI5_TX_1;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI5_TX_1;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI5_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Periph = Periph_SPI5_RX_1;
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI5_RX_1;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI5_RX_1;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI5_BSP_DMA_Receive_Callback;//DMA Callback
	}
	else if (strcmp(WHT_BUS->Info.Name, WHT_SPI6_Name) == 0)
	{
		WHT_BUS->DMA_Send_Config.Periph = Periph_SPI6_TX;
		WHT_BUS->DMA_Send_Config.Stream = Stream_SPI6_TX;
		WHT_BUS->DMA_Send_Config.Channel = Channel_SPI6_TX;
		WHT_BUS->DMA_Send_Config.IT_Callback = WHT_SPI6_BSP_DMA_Send_Callback;      //DMA Callback
		WHT_BUS->DMA_Receive_Config.Periph = Periph_SPI6_RX;
		WHT_BUS->DMA_Receive_Config.Stream = Stream_SPI6_RX;
		WHT_BUS->DMA_Receive_Config.Channel = Channel_SPI6_RX;
		WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_SPI6_BSP_DMA_Receive_Callback;//DMA Callback
	}	
    else
        return;
	WHT_DMA_BSP.WHT_Register(&WHT_BUS->DMA_Send_Config);
    WHT_DMA_BSP.WHT_Register(&WHT_BUS->DMA_Receive_Config);

	WHT_SPI_BUS_NVIC_Configuration(bus);
	WHT_SPI_BUS_Config(bus);
}


/*注册SPI总线*/
static WHT_SPI_BUS_t* WHT_SPI_BUS_Register(char* name, WHT_SPI_BUS_Config_t* config, void (*gpio_init_callback)(void))
{
    char Pos;

    if ((strcmp(name, WHT_SPI1_Name) == 0) && (WHT_SPI_BUS[0] == NULL))
        Pos = 0;
    else if ((strcmp(name, WHT_SPI2_Name) == 0) && (WHT_SPI_BUS[1] == NULL))
        Pos = 1;
    else if ((strcmp(name, WHT_SPI3_Name) == 0) && (WHT_SPI_BUS[2] == NULL))
        Pos = 2;
	else if ((strcmp(name, WHT_SPI4_Name) == 0) && (WHT_SPI_BUS[3] == NULL))
        Pos = 3;
	else if ((strcmp(name, WHT_SPI5_Name) == 0) && (WHT_SPI_BUS[4] == NULL))
        Pos = 4;
	else if ((strcmp(name, WHT_SPI6_Name) == 0) && (WHT_SPI_BUS[5] == NULL))
        Pos = 5;
	else
        return NULL;

    WHT_SPI_BUS[Pos] = malloc(sizeof(WHT_SPI_BUS_Private_t));
    if (WHT_SPI_BUS[Pos])
    {
        WHT_SPI_BUS[Pos]->Info.Name = name;
        memcpy(&WHT_SPI_BUS[Pos]->Info.Config, config, sizeof(WHT_SPI_BUS_Config_t));
        WHT_SPI_BUS[Pos]->GPIO.GPIO_Init_CB = gpio_init_callback;
        WHT_SPI_BUS_Init((WHT_SPI_BUS_t*)WHT_SPI_BUS[Pos]);
        return (WHT_SPI_BUS_t*)WHT_SPI_BUS[Pos];
    }
    return NULL;
}
/*注销软件SPI总线*/
static void WHT_SPI_BUS_Unregister(WHT_SPI_BUS_t* bus)
{
    for (size_t i = 0; i < sizeof(WHT_SPI_BUS) / sizeof(WHT_SPI_BUS[0]); i++)
    {
        if (WHT_SPI_BUS[i] == WHT_BUS)
        {
            WHT_SPI_BUS[i] = NULL;
            free(WHT_BUS);
			break;
        }
    }
}


/*全局常量*/
const WHT_SPI_BUS_OPS_t WHT_SPI_BUS_OPS =
{
    .Register       = WHT_SPI_BUS_Register,
    .Unregister     = WHT_SPI_BUS_Unregister,
    //.Set_Rate     = WHT_SPI_BUS_Set_Rate,
    .Read_Write     = WHT_SPI_BUS_Read_Write,
	.Read_Write_IT  = WHT_SPI_BUS_Read_Write_IT,
	.Read_Write_DMA = WHT_SPI_BUS_Read_Write_DMA,
};



/*SPI中断回调函数*/
static void WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS_Private_t* BUS, unsigned int* tx_count, unsigned int* rx_count)
{
#if 1
	/*这个非连续发送数据，相比连续发送数据更安全。这个不怕被高优先级长时间打断，TXE中断必须关闭*/
	if (spi_i2s_interrupt_flag_get(BUS->SPI_BUS, SPI_I2S_INT_FLAG_TBE) == SET)//TXE事件
	{
		spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_TBE);
		if (BUS->Cache->Dir == SPI_RO)
			spi_i2s_data_transmit(BUS->SPI_BUS, 0xff);
		else
			spi_i2s_data_transmit(BUS->SPI_BUS, BUS->Cache->Tx_Buffer[(*tx_count)++]);
	}
	if (spi_i2s_interrupt_flag_get(BUS->SPI_BUS, SPI_I2S_INT_FLAG_RBNE) == SET)//RXE事件
	{
		if (BUS->Cache->Dir == SPI_WO)//发送
			spi_i2s_data_receive(BUS->SPI_BUS);//丢掉接收的数据
		else//if((BUS->Cache->Dir == SPI_TRx) || (BUS->Cache->Dir == SPI_RO))//接收
			BUS->Cache->Rx_Buffer[(*rx_count)++] =(unsigned char)spi_i2s_data_receive(BUS->SPI_BUS);
		if(*tx_count != BUS->Cache->Buffer_Count)
			spi_i2s_data_transmit(BUS->SPI_BUS, BUS->Cache->Tx_Buffer[(*tx_count)++]);
		else
		{
			if (BUS->Info.Config.NSS == Soft_NSS)
				BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
			spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_TBE);
			spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_RBNE);
			spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_ERR);
			spi_disable(BUS->SPI_BUS);
			*tx_count = *rx_count = 0;
			WHT_SPI_BSP_User_IT_Callback(BUS);
		}
	}
#else//SPI速度快点就会导致不是连续的数据流了
/*
这个可以连续发送数据，即时钟连续状态，可以让SPI高效工作。TXE中断必须打开
这个怕接收到数据了，刚好被高优先级的打断并且时间较长导致接收缓存区溢出,丢失数据的问题
如果接收缓冲区溢出。
*/
	if (spi_i2s_interrupt_flag_get(BUS->SPI_BUS, SPI_I2S_INT_FLAG_RBNE) == SET)//RXE事件
	{
		if (BUS->Cache->Dir == SPI_WO)//MASTER只写
			spi_i2s_data_receive(BUS->SPI_BUS);//丢掉接收的数据
		else//if ((BUS->Cache->Dir == SPI_TRx) || (BUS->Cache->Dir == SPI_RO))//接收
			BUS->Cache->Rx_Buffer[*rx_count] =(unsigned char)spi_i2s_data_receive(BUS->SPI_BUS);
		(*rx_count)++;
		if (*rx_count == BUS->Cache->Rx_Count)
		{
			if (BUS->Cache->NSS == Soft_NSS)
				*BUS->Cache->Sort_NSS = Hig;
			spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_TBE);
			spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_RBNE);
			spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_ERR);
			spi_disable(BUS->SPI_BUS);
			*rx_count = 0;
			WHT_SPI_BSP_User_IT_Callback(BUS);
		}
	}
	if (spi_i2s_interrupt_flag_get(BUS->SPI_BUS, SPI_I2S_INT_FLAG_TBE) == SET)//TXE事件
	{
		if (BUS->Cache->Dir == SPI_RO)
			spi_i2s_data_transmit(BUS->SPI_BUS, 0xff);
		else
			spi_i2s_data_transmit(BUS->SPI_BUS, BUS->Cache->Tx_Buffer[(*tx_count)++]);
		if (*tx_count == BUS->Cache->Buffer_Count)
		{
			spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_TBE);
			*tx_count = 0;
		}
	}
#endif
	if ((spi_i2s_flag_get(BUS->SPI_BUS, SPI_FLAG_CRCERR) == SET) || (spi_i2s_flag_get(BUS->SPI_BUS, SPI_FLAG_CONFERR) == SET) || (spi_i2s_flag_get(BUS->SPI_BUS, SPI_FLAG_RXORERR) == SET))//ERROR
	{
		spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_TBE);
		spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_RBNE);
		spi_i2s_interrupt_disable(BUS->SPI_BUS, SPI_I2S_INT_ERR);
		if (BUS->DMA_State == ENABLE)
		{
			WHT_SPI_BSP_DMA_Send_Receive_Callback(BUS);
		}
		else
		{
			if (spi_i2s_flag_get(BUS->SPI_BUS, SPI_FLAG_RXORERR) == SET)
			{
				spi_i2s_data_receive(BUS->SPI_BUS);//丢掉接收的数据
				*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_Rx_Over_Error;
			}
			else if (spi_i2s_flag_get(BUS->SPI_BUS, SPI_FLAG_CONFERR) == SET)
			{
				spi_i2s_data_receive(BUS->SPI_BUS);//丢掉接收的数据
				*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_BUS_Error;
			}
			else if (spi_i2s_flag_get(BUS->SPI_BUS, SPI_FLAG_CRCERR) == SET)//no crc func
			{
				spi_crc_error_clear(BUS->SPI_BUS);
				*(WHT_SPI_BUS_State_enum*)&BUS->Info.State = SPI_CRC_Error;
			}
			if (BUS->Info.Config.NSS == Soft_NSS)
				BUS->Cache->Set_NSS_State_CB(SPI_IO_Hig);
			spi_disable(BUS->SPI_BUS);
			WHT_SPI_BSP_User_IT_Callback(BUS);
		}
	}
}

/*SPI1 中断服务程序*/
void SPI0_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[0], &tx_count, &rx_count);
}
/*SPI2 中断服务程序*/
void SPI1_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[1], &tx_count, &rx_count);
}
/*SPI3 中断服务程序*/
void SPI2_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[2], &tx_count, &rx_count);
}
/*SPI4 中断服务程序*/
void SPI3_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[3], &tx_count, &rx_count);
}
/*SPI5 中断服务程序*/
void SPI4_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[4], &tx_count, &rx_count);
}
/*SPI6 中断服务程序*/
void SPI5_IRQHandler(void)
{
	static unsigned int tx_count = 0;
	static unsigned int rx_count = 0;

	WHT_SPI_BSP_IRQHandler(WHT_SPI_BUS[5], &tx_count, &rx_count);
}
